#!/bin/bash

# 测试脚本 - 使用LLVM IR测评结果
MINIC_COMPILER="./build/minic"
TEST_DIR="2025_function"
TEMP_DIR="temp_test"
RESULT_FILE="test_results.txt"
STD_DIR="std"

# 创建临时目录
mkdir -p $TEMP_DIR

# 清空结果文件
> $RESULT_FILE

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 统计变量
total_tests=0
passed_tests=0
failed_tests=0

# 输出函数，同时输出到终端和文件
output() {
    echo -e "$1"
    echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g' >> $RESULT_FILE
}

output "开始测试 $TEST_DIR 目录中的测例..."
output "使用编译器: $MINIC_COMPILER"
output "========================================"

# 检查编译器是否存在
if [ ! -f "$MINIC_COMPILER" ]; then
    output "${RED}错误: 找不到编译器 $MINIC_COMPILER${NC}"
    exit 1
fi

# 检查std库文件是否存在
if [ -f "$STD_DIR/std.c" ] && [ -f "$STD_DIR/std.h" ]; then
    USE_STD=true
else
    USE_STD=false
fi

# 遍历所有.c文件
for test_file in $TEST_DIR/*.c; do
    if [ -f "$test_file" ]; then
        total_tests=$((total_tests + 1))
        filename=$(basename "$test_file" .c)
        ir_file="$TEMP_DIR/${filename}.ll"
        out_file="$TEST_DIR/${filename}.out"
        in_file="$TEST_DIR/${filename}.in"
        
        echo -n "测试 $filename ... "
        echo -n "测试 $filename ... " >> $RESULT_FILE
        
        # 编译生成LLVM IR
        if [ "$USE_STD" = true ]; then
            std_ir="$TEMP_DIR/std.ll"
            # 先编译std.c
            if $MINIC_COMPILER -S -L -o "$std_ir" "$STD_DIR/std.c" 2>/dev/null; then
                # 再编译测试文件
                if $MINIC_COMPILER -S -L -o "$ir_file" "$test_file" 2>/dev/null; then
                    # 用llvm-link链接
                    linked_ir="$TEMP_DIR/${filename}_linked.ll"
                    if llvm-link "$std_ir" "$ir_file" -S -o "$linked_ir" 2>/dev/null; then
                        ir_file="$linked_ir"
                        compile_success=true
                    else
                        compile_success=false
                    fi
                else
                    compile_success=false
                fi
            else
                compile_success=false
            fi
        else
            # 不使用std库编译
            if $MINIC_COMPILER -S -L -o "$ir_file" "$test_file" 2>/dev/null; then
                compile_success=true
            else
                compile_success=false
            fi
        fi

        if [ "$compile_success" = true ]; then
            # 先执行并获取返回值
            if [ -f "$in_file" ]; then
                lli "$ir_file" < "$in_file" > "$TEMP_DIR/${filename}_stdout.txt" 2>/dev/null
                exit_code=$?
            else
                lli "$ir_file" > "$TEMP_DIR/${filename}_stdout.txt" 2>/dev/null
                exit_code=$?
            fi

            # 针对特定测例打印实际输出
            if [ "$filename" = "2025_func_021_if_test2" ]; then
                echo "==== $filename 实际输出如下 ===="
                cat "$TEMP_DIR/${filename}_stdout.txt"
                echo "==== $filename 实际输出结束 ===="
            fi

            # 判断预期结果
            if [ -f "$out_file" ]; then
                # 有.out文件，需要判断比较的是标准输出、返回值，还是两者
                mapfile -t out_lines < "$out_file"
                out_lines_count=${#out_lines[@]}
                if [ $out_lines_count -eq 1 ]; then
                    expected_output="${out_lines[0]}"
                    # 检查是否为纯数字（返回值）
                    if [[ "$expected_output" =~ ^[0-9]+$ ]]; then
                        # 只比较返回值
                        if [ "$exit_code" = "$expected_output" ]; then
                            echo -e "${GREEN}PASS${NC} (返回值: $exit_code)"
                            echo "PASS (返回值: $exit_code)" >> $RESULT_FILE
                            passed_tests=$((passed_tests + 1))
                        else
                            echo -e "${RED}FAIL${NC} (实际返回值: $exit_code)"
                            echo "FAIL (实际返回值: $exit_code)" >> $RESULT_FILE
                            failed_tests=$((failed_tests + 1))
                        fi
                    else
                        # 只比较标准输出
                        actual_output=$(cat "$TEMP_DIR/${filename}_stdout.txt")
                        if [ "$actual_output" = "$expected_output" ]; then
                            echo -e "${GREEN}PASS${NC} (输出匹配)"
                            echo "PASS (输出匹配)" >> $RESULT_FILE
                            passed_tests=$((passed_tests + 1))
                        else
                            echo -e "${RED}FAIL${NC} (输出不匹配)"
                            echo "FAIL (输出不匹配)" >> $RESULT_FILE
                            echo "  实际输出:" >> $RESULT_FILE
                            cat "$TEMP_DIR/${filename}_stdout.txt" | sed 's/^/    /' >> $RESULT_FILE
                            failed_tests=$((failed_tests + 1))
                        fi
                    fi
                else
                    # 多行，最后一行为返回值，其余为输出
                    expected_ret="${out_lines[$((out_lines_count-1))]}"
                    expected_output=$(printf "%s\n" "${out_lines[@]:0:$((out_lines_count-1))}")
                    actual_output=$(cat "$TEMP_DIR/${filename}_stdout.txt")
                    output_match=false
                    ret_match=false
                    if [ "$actual_output" = "$expected_output" ]; then
                        output_match=true
                    fi
                    if [ "$exit_code" = "$expected_ret" ]; then
                        ret_match=true
                    fi
                    if [ "$output_match" = true ] && [ "$ret_match" = true ]; then
                        echo -e "${GREEN}PASS${NC} (输出和返回值均匹配)"
                        echo "PASS (输出和返回值均匹配)" >> $RESULT_FILE
                        passed_tests=$((passed_tests + 1))
                    else
                        echo -e "${RED}FAIL${NC} (输出或返回值不匹配)"
                        echo "FAIL (输出或返回值不匹配)" >> $RESULT_FILE
                        if [ "$output_match" != true ]; then
                            echo "  期望输出:" >> $RESULT_FILE
                            echo "$expected_output" | sed 's/^/    /' >> $RESULT_FILE
                            echo "  实际输出:" >> $RESULT_FILE
                            echo "$actual_output" | sed 's/^/    /' >> $RESULT_FILE
                        fi
                        if [ "$ret_match" != true ]; then
                            echo "  期望返回值: $expected_ret" >> $RESULT_FILE
                            echo "  实际返回值: $exit_code" >> $RESULT_FILE
                        fi
                        failed_tests=$((failed_tests + 1))
                    fi
                fi
            else
                # 没有.out文件，比较返回值（单个值）
                if [[ $filename =~ _([0-9]+)_ ]]; then
                    expected=${BASH_REMATCH[1]}
                else
                    expected=0
                fi
                if [ $exit_code -eq $expected ]; then
                    echo -e "${GREEN}PASS${NC} (返回值: $exit_code)"
                    echo "PASS (返回值: $exit_code)" >> $RESULT_FILE
                    passed_tests=$((passed_tests + 1))
                else
                    echo -e "${RED}FAIL${NC} (实际返回值: $exit_code)"
                    echo "FAIL (实际返回值: $exit_code)" >> $RESULT_FILE
                    failed_tests=$((failed_tests + 1))
                fi
            fi
        else
            echo -e "${RED}FAIL${NC} (编译错误)"
            echo "FAIL (编译错误)" >> $RESULT_FILE
            failed_tests=$((failed_tests + 1))
        fi
    fi
done

output "========================================"
output "测试完成!"
output "总计: $total_tests"
output "通过: $passed_tests"
output "失败: $failed_tests"

if [ $failed_tests -eq 0 ]; then
    output "${GREEN}所有测试通过!${NC}"
else
    output "${YELLOW}有 $failed_tests 个测试失败${NC}"
fi

output ""
output "详细结果已保存到: $RESULT_FILE"

# 清理临时文件
rm -rf $TEMP_DIR

# 返回适当的退出码
if [ $failed_tests -eq 0 ]; then
    exit 0
else
    exit 1
fi
